package com.instalinks.android.smspostservice.receiver;

import java.net.URLDecoder;
import java.util.Hashtable;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.telephony.SmsMessage;

import com.instalinks.android.lib.AppHelper;
import com.instalinks.android.lib.UrlData;
import com.instalinks.android.lib.UrlResponse;
import com.instalinks.android.lib.UrlResponse.UrlResponseType;
import com.instalinks.android.smspostservice.utils.AppConfig;
import com.instalinks.android.smspostservice.utils.enums.PhoneParams;

public class SmsReceiver extends BroadcastReceiver {

	private Context mContext;
	private AppConfig mAppCfg;

	private int iSuccessCount = 0;
	private int iInvalidCount = 0;
	private int iDroppedCount = 0;
	private int iFailedCount = 0;
	private int iAvailableFreeCount = 0;

	// private AppNotifications appNotifications;

	private final static int MAX_RETRIES = 1;

	@Override
	public void onReceive(Context context, Intent intent) {

		// this.abortBroadcast();
		// this.appNotifications = new AppNotifications(context);

		this.mContext = context;
		this.mAppCfg = new AppConfig(this.mContext);
		this.mAppCfg.wakeUp(5000);

		Bundle bundle = intent.getExtras();

		SmsMessage msgs = null;
		if (bundle != null) {
			// loadTotalCounts();

			// ---retrieve the SMS message received---
			Object[] pdus = (Object[]) bundle.get("pdus");

			for (int i = 0; i < pdus.length && i < 1; i++) {
				msgs = SmsMessage.createFromPdu((byte[]) pdus[i]);
				SMSProcessingTask tsk = new SMSProcessingTask();
				tsk.execute(msgs);
			}
		}
	}

	private class SMSProcessingTask extends
			AsyncTask<SmsMessage, Void, Boolean> {

		@Override
		protected Boolean doInBackground(SmsMessage... msgs) {
			iSuccessCount = 0;
			iInvalidCount = 0;
			iDroppedCount = 0;
			iFailedCount = 0;
			iAvailableFreeCount = 0;

			return processSMS(msgs[0]);
		}

		@Override
		protected void onPostExecute(Boolean responseValue) {
			saveTotalCounts();
		}
	}

	private boolean processSMS(SmsMessage msg) {
		String sender = msg.getOriginatingAddress();
		String text = msg.getMessageBody();

		if (!mAppCfg.isConnectedToNetwork() || !mAppCfg.isValidDataNetwork()) {
			try {
				iFailedCount++;

				sendFailAutoReply(sender);
			} catch (Exception e) {
				mAppCfg.alert("No/Invalid Data Network");
				return false;
			}
			return true;
		}

		return processSMS(sender, text);
	}

	private void saveTotalCounts() {
		try {
			mAppCfg.setSmsSuccessCount(mAppCfg.getSmsSuccessCount()
					+ iSuccessCount);
		} catch (Exception e) {
		}
		try {
			mAppCfg.setSmsInvalidCount(mAppCfg.getSmsInvalidCount()
					+ iInvalidCount);
		} catch (Exception e) {
		}
		try {
			mAppCfg.setSmsDroppedCount(mAppCfg.getSmsDroppedCount()
					+ iDroppedCount);
		} catch (Exception e) {
		}

		try {
			mAppCfg.setSmsFailedCount(mAppCfg.getSmsFailedCount()
					+ iFailedCount);
		} catch (Exception e) {
		}

		try {
			mAppCfg.setAvailableFreeCount(mAppCfg.getAvailableFreeCount()
					+ iAvailableFreeCount);
		} catch (Exception e) {
		}
	}

	private boolean processSMS(String sSender, String sText) {

		String sender = sSender.replace("+", "");

		boolean responseValue = false;

		iAvailableFreeCount--;

		boolean doProcess = false;

		if (sText.length() == 0) {
			iInvalidCount++;
		} else if (mAppCfg.isAlphanumericSenderFlag()
				|| AppHelper.isValidPhoneNumber(sender)
				|| (mAppCfg.isShortcodeSenderFlag() && AppHelper
						.isValidShortCode(sender))) {
			doProcess = true; // PROCESS ALL SMS
		} else {
			iInvalidCount++;
		}

		if (doProcess) {
			UrlResponse result = processUrlPosting(sender, sText);

			if (result.getResponseType() == UrlResponseType.success) {
				iSuccessCount++;
				responseValue = true;
				
				try{
					AppHelper.updateSMS(mContext, sSender, sText, "[POSTED]",mAppCfg.isMarkAsReadFlag());
				}catch(Exception e){
					mAppCfg.alert("Error marking SMS as read " + e.getMessage());
				}
				
				String autoResponse = result.getMessage();
				
				if (mAppCfg.isAutoReplyFlag() && AppHelper.isValidPhoneNumber(sender))
					AppHelper.sendSms(mContext,sSender, autoResponse);

			} else if (result.getResponseType() == UrlResponseType.invalid) {
				iInvalidCount++;
			} else if (result.getResponseType() == UrlResponseType.dropped) {
				iDroppedCount++;
				sendFailAutoReply(sSender);
			} else {// if (result.getResponseType() ==
					// UrlResponseType.failed) {
				iFailedCount++;
			}
		}

		return responseValue;
	}

	private void sendFailAutoReply(String sender) {
		try {
			boolean failAutoReply = mAppCfg.isAutoReplyFlag();
			String failedMsg = URLDecoder.decode(mAppCfg.getFailReplyMsg(),
					"UTF-8");

			if (failAutoReply)
				AppHelper.sendSms(mContext, sender, failedMsg);
		} catch (Exception e) {
			mAppCfg.alert("No/Invalid Data Network");
		}
	}

	private UrlResponse processUrlPosting(String sSender, String sText) {

		UrlData urlPost = new UrlData(mAppCfg.getDataPostUrl(), 25000);
		
		UrlResponse result = new UrlResponse(UrlResponseType.exception, "");

		for (int i = 0; i < MAX_RETRIES
				&& result.getResponseType() == UrlResponseType.exception; i++) {
			Hashtable<String, String> htParams = mAppCfg.getDataPostHashtable();

			htParams.put(PhoneParams.sender.toString(), sSender);
			htParams.put(PhoneParams.text.toString(), sText);

			try {
				result = urlPost.postData(htParams);
			} catch (Exception e) {
				result = new UrlResponse(UrlResponseType.exception, "");
			}

			if (result.getResponseType() == UrlResponseType.exception
					&& i == MAX_RETRIES - 1) {
				result.setResponseType(UrlResponseType.dropped);
			}
		}

		return result;
	}

}
